using AOT;
using System;
using System.IO;
using UnityEngine;

namespace UnityX
{
    public partial class RecorderVideo
    {
        public enum Status
        {
            Idle,
            Recording,
            //Pauseing,
            Stoping,
            Finish,
        }
        public Status status { get; private set; }

        public string path { get; private set; }

        private int x = 0;
        private int y = 0;
        public int width { get; private set; }
        public int height { get; private set; }
        public float frameRate { get; private set; }
        private int videoBitRate = 10_000_000;
        private int sampleRate = 0;
        private int channelCount = 0;
        private int audioBitRate = 64_000;
        private int keyframeInterval = 2;
        //
        private IntPtr recorder = IntPtr.Zero;
        //纳秒的开始时间
        private long beginTime = 0;
        //纳秒的现在时间
        private long nowTime { get { return DateTime.Now.Ticks * 100L; } }
        //纳秒的持续时长
        private long duration = 0;

        private GameObject gameObject = null;

        /// <summary>
        /// 创建RecordVideo对象
        /// </summary>
        /// <exception cref="InvalidOperationException"></exception>
        public RecorderVideo()
        {
            string directory;
            switch (Application.platform)
            {
                case RuntimePlatform.IPhonePlayer:
                case RuntimePlatform.Android:
                    directory = Application.persistentDataPath + "/RecordVideo";
                    break;
                default:
                    directory = Directory.GetCurrentDirectory() + "/RecordVideo";
                    break;
            }
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
            path = directory + "/" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_fff") + ".mp4";
            ChackPath(path);
        }
        /// <summary>
        /// 创建RecordVideo对象
        /// </summary>
        /// <param name="path">视频路径</param>
        /// <exception cref="InvalidOperationException"></exception>
        public RecorderVideo(string path)
        {
            this.path = path;
            ChackPath(path);
            string directory = Path.GetDirectoryName(path);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
        }
        private void ChackPath(string path)
        {
            foreach (char c in path)
            {
                if (c < 8 || c > 126)
                {
                    throw new InvalidOperationException(@"录像路径不支持非英文字符：" + path);
                }
            }
        }

        public void Record()
        {
            if (status != Status.Idle)
                return;

            if (videoInputType == VideoInputType.Unknown)
            {
                throw new InvalidOperationException("未设置视频输入！请调用SetVideoInput函数设置一个视频输入类型！");
            }

            RecorderVideoNativeAPI.CreateMP4Recorder(path, width, height, frameRate, sampleRate, channelCount, videoBitRate, keyframeInterval, audioBitRate, out recorder);
            if (recorder == IntPtr.Zero)
            {
                throw new InvalidOperationException(@"创建MP4记录器失败");
            }

            gameObject = new GameObject("_RecordVideo_");
            gameObject.hideFlags = HideFlags.HideInHierarchy;
            UnityEngine.Object.DontDestroyOnLoad(gameObject);

            CreateVideoCommit();
            CreateAudioCommit();

            beginTime = nowTime;
            status = Status.Recording;
        }
        public void Stop()
        {
            if (status != Status.Recording)
                return;

            status = Status.Stoping;

            DestroyVideoCommit();
            DestroyAudioCommit();

            if (gameObject != null)
            {
                UnityEngine.Object.Destroy(gameObject);
                gameObject = null;
            }

            RecorderVideoNativeAPI.FinishWriting(recorder, OnRecorderCompleted, IntPtr.Zero);
        }
        [MonoPInvokeCallback(typeof(RecorderVideoNativeAPI.RecordingHandler))]
        private static unsafe void OnRecorderCompleted(IntPtr context, IntPtr path)
        {
        }
    }
}